﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using MoonLight.LibCommon;
using PortScan.LibCommon;
using PortScan.Business;

namespace PortScan
{
    class Program : Notifier
    {
        public Program()
        {
            port_list = new List<int>();
            thread_list = new List<Thread>();
            mtx = new Mutex();
        }

        public override void handle_message(MessageInfo msg)
        {
            switch ((ProjectDefine.ProjectMsgType_e)msg.msg_type)
            {
                case ProjectDefine.ProjectMsgType_e.MSG_PORT:
                    {
                        mtx.WaitOne();
                        port_list.Add(Convert.ToInt32(msg.msg_data));
                        mtx.ReleaseMutex();
                    }
                    break;
                case ProjectDefine.ProjectMsgType_e.MSG_THREAD_END:
                    {
                        mtx.WaitOne();
                        thread_count--;
                        mtx.ReleaseMutex();
                        if (thread_count == 0)
                        {
                            for (int i = 0; i < port_list.Count; i++)
                            {
                                Console.WriteLine("port[{0}] is open", port_list[i]);
                            }
                            Logger.CloseLog();
                            Console.WriteLine("press any key to exit...");
                            Console.ReadKey();
                        }
                    }
                    break;
                default:
                    {
                        Logger.WriteLog("unknown msg type [" + msg.msg_type.ToString() + "]");
                    }
                    break;
            }
        }

        public List<int> port_list;
        public List<Thread> thread_list;
        public Mutex mtx;
        public int thread_count;

        static void Main(string[] args)
        {
            MoonLight.LibCommon.Logger.SetLogPath();
            Program program = new Program();

#if true
            string ip = "172.18.244.23";
            //string ip = "169.254.193.160";
            int start = 25;
            int end = 25;
            int thread_num = 1;
#endif

#if false
            if (args.Length != 4)
            {
                Console.WriteLine("wrong arg number");
                return;
            }

            string ip = args[0].ToString();
            int start = Convert.ToInt32(args[1]);
            int end = Convert.ToInt32(args[2]);
 
            if (start < 0 || end > 65535)
            {
                Console.WriteLine("wrong ports [{0}-{1}]", start, end);
                return;
            }

            int thread_num = Convert.ToInt32(args[3]);
            if (thread_num <= 0 && thread_num > 8)
            {
                Console.WriteLine("wrong thread number");
            }
#endif
            int ports_per_thread = (end - start + 1) / thread_num;
            program.thread_count = thread_num;

            for (int i = 0; i < thread_num; i++)
            {
                ProjectDefine.thread_info info;
                info.start_port = start + i * ports_per_thread;
                info.end_port = ((start + (i + 1) * ports_per_thread - 1) > end) ? end : (start + (i + 1) * ports_per_thread - 1);
                info.ip = ip;
                //Console.WriteLine("create [{0}] thread [{1}-{2}][{3}]", i, info.start_port, info.end_port, info.ip);
                ScanProcess sp = new ScanProcess(program);
                Thread thread = new Thread(new ParameterizedThreadStart(sp.start_scan));
                thread.Start(info);
            }
            Console.ReadKey();
        }
    }
}
